(function() {
    Nokia.Scroll = Nokia.Widget.extend({
        initialize: function(options) {
            var instance = this;

			var defaults = {
				increase: 100,
				duration: 200,
				scrollBar: true,
				showArrows: false,
				bottomImage: true
            };

            instance.options = jQuery.extend(defaults, options);

            instance._super.apply(instance, [instance.options]);

            var element = instance.options.element ? jQuery(instance.options.element) : (jQuery.browser.mozilla ? jQuery('html') : jQuery('body'));

            instance.element = element;

            //veryfy if element is body or html
            instance.isBody = (/(html|body)/).test(element[0].tagName.toLowerCase());

			// firefox pixel fix
			instance.pixelFix = jQuery.browser.mozilla ? 1 : 0;

			// jQuery's window and document references - best for performance
			instance.document = jQuery(document);
			instance.window = jQuery(window);

			// create arrows
            if (instance.options.showArrows) {
            	instance.arrowUp = instance._createArrow(instance.Directions.UP);
				instance.arrowDown = instance._createArrow(instance.Directions.DOWN);
				instance._positionArrows();
            }

			// create scroll bar
			if (instance.options.scrollBar) {
				instance._createScrollBar();
				instance._updateScrollBarPosition();
			}

			if (instance.options.bottomImage) {
				var imageDiv = Nokia.dom.parseHTML('<div class="ui-widget-overlay" style="height: 100px; position: relative;"></div>');

				Nokia.dom.append(element, imageDiv);
			}

			instance._scrollListener();

			instance.scrollHeight = instance.isBody ? instance.document.height() : element[0].scrollHeight;
			instance.scrollTop = instance.isBody ? instance.window.scrollTop() : element.scrollTop();

			instance._attachEvents();

			setInterval(function() {

				if ( !instance._hasScrolled() ) {
					return;
				}

				instance._scrollListener();

				if ( instance.options.showArrows ) {
					instance._positionArrows();
				}

				if ( instance.options.scrollBar ) {
					instance._updateScrollBar();
					instance._updateScrollBarPosition();
				}

			}, 100);

			instance.registerVibrationOn([ 'create', 'scroll' ]);
			instance.fireCallback('create');
        },

		_attachEvents: function() {
			var instance = this,
				options = instance.options,
				element = instance.isBody ? instance.window : instance.element;

			window.addEventListener('resize', function() {
				instance._scrollListener();

				if ( options.showArrows ) {
					instance._positionArrows();
				}

				if ( options.scrollBar ) {
					instance._updateScrollBar();
					instance._updateScrollBarPosition();
				}
			}, false);

			element.bind('scroll', function() {
				instance._scrollListener();

				if (options.scrollBar) {
					instance._updateScrollBar();
				}
			});
		},

		_createArrow: function(direction) {
			var instance = this,
				options = instance.options,
				element = instance.element;

			var arrow = Nokia.dom.parseHTML('<a href="javascript:void(0);" class="nokia-scroll-arrow nokia-scroll-arrow-' + direction + '"></a>');

			arrow.click(function() {
				var classActive = 'nokia-scroll-arrow-' + direction + '-active';

				arrow.addClass(classActive);

				instance.scroll(direction, function() {
					arrow.removeClass(classActive);
				});
			});

			Nokia.dom.append(element, arrow);

			return arrow;
		},

		_createScrollBar: function() {
			var instance = this,
				element = instance.element;

			instance.barWrapper = Nokia.dom.parseHTML('<div class="ui-state-default nokia-scroll-wrapper"></div>');
			instance.roller = Nokia.dom.parseHTML('<div class="ui-state-active nokia-scroll-roller"></div>');

			Nokia.dom.append(instance.barWrapper, instance.roller);
			Nokia.dom.append(element, instance.barWrapper);

			instance.rollerHeight = instance.roller.height();
		},

		_getScrollPercent: function() {
			var instance = this,
				element = instance.isBody ? instance.window : instance.element,
				height = instance.isBody ? window.innerHeight : element.height();

			return (element.scrollTop() / (( instance.isBody ? instance.document.height() : element[0].scrollHeight ) - height));
		},

		_hasScrolled: function() {
			var instance = this;
			var scrollHeight = instance.isBody ? instance.document.height() : instance.element[0].scrollHeight;
			var scrollTop = instance.isBody ? instance.window.scrollTop() : instance.element.scrollTop();

			var scrolled = !(scrollTop == instance.scrollTop && scrollHeight == instance.scrollHeight);

			instance.scrollHeight = scrollHeight;
			instance.scrollTop = scrollTop;

			return scrolled;
		},

		_positionArrows: function() {
			var instance = this,
				element = instance.element,
				width = element.width(),
				height = instance.isBody ? window.innerHeight : element.height();

			instance.arrowUp.css({
				left: element.offset().left + width - 41,
				top: (instance.isBody ? 0 : element.offset().top) + 5
			});

			instance.arrowDown.css({
				left: element.offset().left + width - 41,
				top: (instance.isBody ? window.innerHeight :  element.offset().top + height) - 41
			});

			instance.arrowUp.css('position', instance.isBody ? 'fixed' : 'absolute');
			instance.arrowDown.css('position', instance.isBody ? 'fixed' : 'absolute');
		},

		_scrollListener: function() {
			var instance = this
				options = instance.options;

			var height = instance.isBody ? window.innerHeight : instance.element.height();
			var scrollHeight = instance.isBody ? instance.document.height() : instance.element[0].scrollHeight;
			var scrollTop = instance.isBody ? instance.window.scrollTop() : instance.element.scrollTop();

			var isTop = scrollTop <= 0;
			var isBottom = scrollHeight - (scrollTop + height) <= 0;

			if (options.showArrows) {

				instance.showArrows();

				if ( isTop ) {
					instance.hideArrows(instance.arrowUp);
				}

				if ( isBottom ) {
					instance.hideArrows(instance.arrowDown);
				}

			}

			if ((isTop && isBottom) && options.scrollBar) {
				instance.barWrapper.hide();
			} else {
				instance.barWrapper.show();
			}

		},

		_updateScrollBar: function() {
			var instance = this,
				percent = instance._getScrollPercent() || 0;

			instance.roller.css( { top: ( percent * ( instance.barWrapperHeight - instance.rollerHeight ) ) });
		},

		_updateScrollBarPosition: function() {
			var instance = this,
				options = instance.options,
				offset = instance.element.offset(),
				top = instance.isBody ? 0 : offset.top,
				right = instance.isBody ? 0 : window.innerWidth - (offset.left + instance.element.outerWidth()),
				height = instance.isBody ? window.innerHeight : instance.element.outerHeight();

			if ( !options.showArrows ) {
				instance.barWrapper.css({
					height: height - 2,
					top: top,
					right: right
				});
			} else {
				instance.barWrapper.css({
					height: height - 92,
					right: right + (instance.isBody ? 15 : 17),
					top: top + 46
				});
			}

			instance.barWrapperHeight = instance.barWrapper.height();

			if (instance.isBody) {
				instance.barWrapper.css('position', 'fixed');
			} else {
				instance.barWrapper.css('position', 'absolute');
			}
		},

		hideArrows: function(arrow) {
			var instance = this;

			if (arrow) {
				arrow.hide();
			} else {
				instance.arrowUp.hide();
				instance.arrowDown.hide();
			}

		},

		scroll: function(direction, callback) {
			var instance = this,
				options = instance.options,
				element = instance.element,
				increase = options.increase,
				duration = options.duration;

			increase = increase * (direction == instance.Directions.UP ? -1 : 1 );

			element.animate({ scrollTop: '+=' + increase }, duration, function(){

				if (callback) {
					callback.apply(instance, []);
				}

				instance.fireCallback('scroll');
			});
		},

		showArrows: function(arrow) {
			var instance = this;

			if (arrow) {
				arrow.show();
			} else {
				instance.arrowUp.show();
				instance.arrowDown.show();
			}

		},

		Styles: {
			arrowClass: 'nokia-scroll-arrow',
			activeClass: 'nokia-scroll-arrow-active',
			disabledClass: 'nokia-scroll-disabled'
		},

		Directions: {
			UP: 'up',
			DOWN: 'down'
		}
    });
})();